package us.lithub.ui.activity;

import java.util.List;

import us.lithub.R;
import us.lithub.Util;
import us.lithub.data.Book;
import us.lithub.data.GlobalDb;
import us.lithub.data.WebConnector;
import us.lithub.ui.dialog.AddBookManually;
import us.lithub.ui.dialog.PreviewAddedBook;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;

/**
 * The Class ScanBook.
 */
public class ScanBook extends Activity {

	// Intents to check to make sure we have the market and the scanner
	private static final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=dummy"));
	private static final Intent scanIntent = new Intent("com.google.zxing.client.android.SCAN");

	// Request codes used to differentiate between the different startActivityForResult calls
	private static final int SCAN_REQUEST = 1;
	private static final int MANUAL_REQUEST = 2;
	private static final int PREVIEW_REQUEST = 3;

	/* (non-Javadoc)
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_scan_book);
		begin();
	}

	/**
	 * This is the main 'loop' that we can return to in orer to scan more books.
	 */
	private void begin() {
		if (!hasCamera()) {
			// They don't have a camera, so we can't scan even if we install the scanner app
			cantScan();
		} else if (isInstalled(scanIntent)) {
			// They have the scanner installed, let's scan the book
			scan();
		} else if (hasCamera() && isInstalled(marketIntent)) {
			// They don't have the scanner installed but can, get it from the market
			getScannerFromMarket();
		} else {
			cantScan();
		}
	}

	/**
	 * Check if the phone physically has a camera.
	 *
	 * @return true if the phone has a camera, false otherwise
	 */
	private boolean hasCamera() {
		return getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
	}

	/**
	 * Check if an app is installed by checking to see if the intent is callable.
	 *
	 * @param intent The intent that we wish to call
	 * @return true if the app is installed, false otherwise
	 */
	private boolean isInstalled(Intent intent) {  
		List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);  
		return list.size() > 0;  
	}

	/**
	 * Launch the scanner to scan a book.
	 */
	private void scan() {
		scanIntent.putExtra("SCAN_MODE", "PRODUCT_MODE");
		startActivityForResult(scanIntent, SCAN_REQUEST);
	}

	/**
	 * The phone does not meet the minimum specs and cannot scan.  Give the option to scan manually or to simply finish the activity
	 */
	private void cantScan() {
		AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
		alertbox.setMessage("Your device cannot scan books, would you like to enter a upc manually?");
		alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {  		 

			@Override
			public void onClick(DialogInterface arg0, int arg1) {
				enterManually();
			}
		});
		alertbox.setNegativeButton("No", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				finish();	
			}
		});
		alertbox.show();
	}

	/**
	 * Start a dialog activity that allows the user to enter an isbn manually.
	 */
	private void enterManually() {
		Intent manualIntent = new Intent(this, AddBookManually.class);
		startActivityForResult(manualIntent, MANUAL_REQUEST);
	}

	/**
	 * Gives the user the option to either download the scanner app from the market and then finish this activity (return to the main menu)
	 * or to enter an isbn manually to add a book that way.
	 *
	 * @return the scanner from market
	 */
	private void getScannerFromMarket() {
		AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
		alertbox.setMessage("Barcode Scanner not found.  Would you like to get it now?");
		alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {  		 

			@Override
			public void onClick(DialogInterface arg0, int arg1) {
				Intent intent = new Intent(Intent.ACTION_VIEW);
				intent.setData(Uri.parse("market://details?id=com.google.zxing.client.android&hl=en"));
				startActivity(intent);
				finish();
			}
		});
		alertbox.setNegativeButton("No", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				enterManually();		
			}
		});
		alertbox.show();
	}

	/**
	 * Launch the preview dialog to let the user accept or deny the addition of the book to their library.
	 *
	 * @param upc The upc or ISBN of the book
	 */
	private void showPreviewForBook(String upc) {
		Intent previewIntent = new Intent(this, PreviewAddedBook.class);
		previewIntent.putExtra(Book.UPC, upc);
		startActivityForResult(previewIntent, PREVIEW_REQUEST); 
	}

	private void addBook(String isbn) {
		GlobalDb gdb = new GlobalDb(this);
		gdb.open();
		
		if(!gdb.bookExists(isbn)) {
			gdb.addBook(isbn);
		}
		
		WebConnector wc = WebConnector.getInstance();
		wc.addBook(Util.getUsername(this), Util.getPassword(this), isbn);
		
		gdb.close();
		finish();
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
		switch (requestCode) {
		case SCAN_REQUEST:
			if (resultCode == RESULT_OK) {
				String upc = intent.getStringExtra("SCAN_RESULT");
				showPreviewForBook(upc);
			}
			break;
		case MANUAL_REQUEST:
			if (resultCode == RESULT_OK) {
				String upc = intent.getStringExtra("MANUAL_RESULT");
				showPreviewForBook(upc);
			}
			break;
		case PREVIEW_REQUEST:
			if (resultCode == RESULT_OK) {
				String isbn = intent.getStringExtra(Book.ISBN);
				addBook(isbn);
			} else {
				begin();
			}
			break;
		}
	}
}